package com.cas;

import ch.qos.logback.core.util.TimeUtil;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * ABA 问题
 */
public class ABA {


    public static void main(String[] args) {

//        abaQuestionCreate();

        abaQuestionSolve();
    }

    /**
     * ABA 问题解决
     * 使用一个版本号与变量绑定，每次修改对时候，版本号+1
     */
    private static void abaQuestionSolve() {
        AtomicStampedReference<Integer> integerAtomicStampedReference = new AtomicStampedReference<>(10, 1);

        new Thread(()->{

            try {

                TimeUnit.SECONDS.sleep(1);
            }catch (Exception e){

            }
            integerAtomicStampedReference.compareAndSet(10,20,integerAtomicStampedReference.getStamp(),integerAtomicStampedReference.getStamp() + 1);
            integerAtomicStampedReference.compareAndSet(20,10,integerAtomicStampedReference.getStamp(),integerAtomicStampedReference.getStamp() + 1);

            try {

                TimeUnit.SECONDS.sleep(1);
            }catch (Exception e){

            }

        }).start();


        try {

            int beforeStamp = integerAtomicStampedReference.getStamp();
            TimeUnit.SECONDS.sleep(3);

            integerAtomicStampedReference.compareAndSet(10,100,beforeStamp,beforeStamp + 1);
        }catch (Exception e){

        }

        System.out.println("最后 value :" + integerAtomicStampedReference.getReference());
    }


    /**
     * ABC 问题对产生
     */
    private static void abaQuestionCreate() {
        AtomicInteger atomicInteger = new AtomicInteger(10);

        new Thread(()->{

            atomicInteger.compareAndSet(10,20);
            atomicInteger.compareAndSet(20,10);

            try {

                TimeUnit.SECONDS.sleep(1);
            }catch (Exception e){

            }
        }).start();


        try {

            TimeUnit.SECONDS.sleep(5);
        }catch (Exception e){

        }

        atomicInteger.compareAndSet(10,30);

        System.out.println("current value =" + atomicInteger.get());
    }

}
